<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">

body, html,#allmap {width: 100%;height: 96%;overflow: hidden;margin:0;}

</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=9fb983ecd9b505f8fedcc9ab07c65e3e"></script>
<script type="text/javascript" src="http://developer.baidu.com/map/jsdemo/demo/convertor.js"></script>
<script type="text/javascript" src="js/correction.js"></script>
<script type="text/javascript" src="js/tools.js"></script>
<script type="text/javascript" src="js/DistanceTool.js"></script>
<script type="text/javascript" src="points-data.js"></script>


<title>GPS坐标转百度</title>
</head>
<body>
<div id="allmap"></div>
<div id="control">
    <input type="button" value="开启测距" align="right" onclick="myDis.open()" />
    <input type="button" value="关闭测距" align="right" onclick="myDis.close()" />
    <img src="red.png" />188<input type="checkbox" id="188" checked="checked"/> <img src="oo.png" />180<input type="checkbox" id="180" checked="checked"/> <img src="blue.png" />Android<input type="checkbox" id="android" checked="checked"/><input type="button" value="更新显示" align="right" onclick="check_draw()" /><input type="button" value="清除所有" align="right" onclick="bm.clearOverlays()" />
</div>

<script type="text/javascript">
//GPS坐标
var xx = 114.463131;
var yy = 38.02623732;
var gpsPoint = new BMap.Point(xx,yy);

//地图初始化
var bm = new BMap.Map("allmap");
bm.centerAndZoom(gpsPoint, 15);
bm.enableScrollWheelZoom();                    //开启鼠标滚轮控制缩放
bm.addControl(new BMap.NavigationControl());   //地图平移缩放控件
bm.addControl(new BMap.ScaleControl());        //比例尺控件
bm.addControl(new BMap.OverviewMapControl());  //缩略地图控件
bm.addControl(new BMap.MapTypeControl());      //地图类型控件
var myDis = new BMapLib.DistanceTool(bm);

function GenInfoWindow(id, point, cno, speed) {
    var divInfo = "<strong title='" + id + "' style='font-size: 18px;'>" + id + "</strong><div>经度: " + point[0] + "</div><div>纬度: " + point[1] + "</div>";
    var speedInfo = "<div>速度: " + speed + " m/s</div>";
    var cnoInfo = "<div><div>方向: " + cno + "</div></div>"

    divInfo = divInfo + speedInfo + cnoInfo;
    return new BMap.InfoWindow(divInfo);
}

function create_markers(id, _point, _cno, _speed) {
    var point = new BMap.Point(_point[1], _point[0]);
    
    var icon = new BMap.Icon('image/red.png', new BMap.Size(10, 20), {anchor: new BMap.Size(10, 15)});

    var marker = new BMap.Marker(point,{icon: icon});

    var iw = GenInfoWindow(id, _point, _cno, _speed);
    marker.addEventListener("click", function() {
        marker.openInfoWindow(iw);
    });

    var label = new BMap.Label(String(id),{offset:new BMap.Size(20,-10)});
    //marker.setLabel(label); //添加百度label

    marker.setRotation(_cno);

    bm.addOverlay(marker);

    bm.setCenter(point);
}

function filter_move_stop()
{
    var _lastpoint = [0,0];
    var _above = 0;
    var points = [];
    var speeds = [];
    var cnos = [];

    //提取记录点
	for (var i = 0; i < data.data.length; i++) {
        var _point = wgs2bd(data.data[i][1], data.data[i][0]);
        var _speed = data.speed[i];
        var _cno = data.cno[i];

        points.push(_point);
        speeds.push(_speed);
        cnos.push(_cno);
	}

	var t = 5;
	var start = 220;
	var end = 380;
	var _lastpoint;
	var watch_flag = 0;	//判断条件，速度递减
	var d_speed_count = 0;	//速度递减次数
	var contiue_d_count = 0; //连续减速
	var d_flag = 0;	//降速

    for (var i = start; (i < end) && (mode & 0x1); ) {
        var _point = points[i];
        var _cno = cnos[i];
        var _speed = speeds[i];
        var _bPoint;

        //v1
        /*if (_speed < 3 && _above == 1)
        {
            _point = _lastpoint;
        }
        else
        {
            _above = 1;
        }*/

        //alg1可用于抑制路口等待导致的偏移
        //使用连续减速与连续加速为先验条件，然后过滤减速到静止过程造成的点漂移
        if (i >= start + 5)
        {
        	_bPoint = points[i-t];
        	var p1 = new BMap.Point(_bPoint[1], _bPoint[0]);
        	var p2 = new BMap.Point(_point[1], _point[0]);

        	var dis = bm.getDistance(p1,p2);
        	var v = (speeds[i-t+0] + speeds[i-t+1] + speeds[i-t+2] + speeds[i-t+3] + speeds[i-t+4] + speeds[i-t+5])/6;

        	console.log("id:%d dis:%d, v:%d, v1:%d", i, dis, v, dis/5);

        	//a 判断连续减速趋势
        	//速度已经降到10m/s以下
        	//第i个点与第i-5个点速度至少相差4m/s
        	if (speeds[i-5] - speeds[i] >= 4 && speeds[i] < 10) {
        		var d_count = 0;
        		for (var j = 0; j < 5; j++) {
        			if (speeds[i-5+j] > speeds[i-5+j+1] )
        				d_count ++;
        		}

        		//6个点至少三次降速
        		if (d_count > 3) {
        			d_flag = 1;
        		}
        	}

        	//b 判断连续加速趋势
        	//速度已经高于8m/s
        	//统计临近6个点的速度值增量变化
			if (speeds[i] > 8) {
        		var i_count = 0;
        		for (var j = 0; j < 5; j++) {
        			if (speeds[i-5+j] < speeds[i-5+j+1] )
        				i_count ++;
        		}

        		//6个点至少三次降速
        		if (i_count > 3) {
        			d_flag = 0;
        		}
        	}

        	//c 降速过程，判断过滤漂移点
        	if (d_flag) {
				//if (_speed <= 5)
		        {
		            _point = _lastpoint;
		        }
        	}
        	_lastpoint = _point;
        }
        
        create_markers(i, _point, _cno, _speed);
        i+= 1;

    }
}

//归一化
function normalize(_points)
{
	var max_lon = 0, max_lat = 0;
	var min_lon = 0, min_lat = 0;
	var tmp_lon = 0, tmp_lat = 0;
	var n = _points.length;
	var points = _points.slice();
	var nor_points = [];

	//升序排序
	for (var i = 0; i < n-1; i++) {
		for (var j = i+1; j < n; j++) {
			
			if (points[i][0] > points[j][0]) {
				tmp_lon = points[i][0];
				points[i][0] = points[j][0];
				points[j][0] = tmp_lon;
			}

			if (points[i][1] > points[j][1]) {
				tmp_lat = points[i][1];
				points[i][1] = points[j][1];
				points[j][1] = tmp_lat;
			}
		}
	}

	//归一化
	for (var i = 0; i < n; i++){
		tmp_lon = (points[i][0] - min_lon)/(max_lon - min_lon);
		tmp_lat = (points[i][1] - min_lon)/(max_lon - min_lon);
		nor_points.push([tmp_lon, tmp_lat]);
	}

	return nor_points;
}

//计算线性回归方程y=bx+a系数: a,b
function line_regression(points)
{
	var avg_lon = 0.0;
	var avg_lon_num = 0.0;
	var avg_lat = 0.0;
	var avg_lat_num = 0.0;

	var sum_lon = 0.0;
	var sum_lat = 0.0;
	var num = points.length;
	var a_lon = 0.0, b_lon = 0.0;
	var a_lat = 0.0, b_lat = 0.0;

	//求和
	for (var i = n - 1; i >= 0; i--) {
		sum_lon += points[i][0];
		sum_lat += points[i][1];
	}

	avg_lon = sum_lon/num;
	avg_lat = sum_lat/num;

	avg_lat_num = avg_lon_num = (1+num)*num/2/num;

	//计算参数b
	var sum_lon_dif = 0, sum_lon_dif = 0, sum_lon_same = 0, sum_lat_same = 0;
	for (var i = n - 1; i >= 0; i--) {
		sum_lon_dif += (points[i][0] - avg_lon)*(i + 1 - avg_lon_num);
		sum_lon_same += (points[i][0] - avg_lon)*(points[i][0] - avg_lon);

		sum_lat_dif += (points[i][1] - avg_lat)*(i + 1 - avg_lat_num);
		sum_lat_same += (points[i][1] - avg_lat)*(points[i][1] - avg_lat);
	}

	b_lon = sum_lon_dif/sum_lon_same;
	b_lat = sum_lat_dif/sum_lat_same;

	//计算参数a
	a_lon = avg_lon - b_lon*avg_lon_num;
	a_lat = avg_lat - b_lat*avg_lat_num;

	console.log("b# lon:%.4f lat:%.4f a# lon:%.4f lat:%.4f", b_lon, b_lat, a_lon, a_lat);

	return [[b_lon, a_lon], [b_lat, a_lat]];
}

function line_regression_ex(points, begin, count)
{
	var avg_lon = 0.0;
	var avg_lon_num = 0.0;
	var avg_lat = 0.0;
	var avg_lat_num = 0.0;

	var sum_lon = 0.0;
	var sum_lat = 0.0;
	var num = begin + count;
	var a_lon = 0.0, b_lon = 0.0;
	var a_lat = 0.0, b_lat = 0.0;
	var sum_lon_dif = 0.0, sum_lat_dif = 0.0, sum_lon_same = 0.0, sum_lat_same = 0.0;

	//求和
	for (var i = num - 1; i >= begin; i--) {
		sum_lon += points[i][0];
		sum_lat += points[i][1];
	}

	avg_lon = sum_lon/num;
	avg_lat = sum_lat/num;

	avg_lat_num = avg_lon_num = (1+num)*num/2/num;

	//计算参数b
	for (var i = num - 1; i >= begin; i--) {
		sum_lon_dif += (points[i][0] - avg_lon)*(i + 1 - avg_lon_num);
		sum_lon_same += (points[i][0] - avg_lon)*(points[i][0] - avg_lon);

		sum_lat_dif += (points[i][1] - avg_lat)*(i + 1 - avg_lat_num);
		sum_lat_same += (points[i][1] - avg_lat)*(points[i][1] - avg_lat);
	}

	//console.log("#%d diff# lon:%f lat:%f same# lon:%f lat:%f", begin, sum_lon_dif, sum_lat_dif, sum_lon_same, sum_lat_same);

	b_lon = sum_lon_dif/sum_lon_same;
	b_lat = sum_lat_dif/sum_lat_same;

	//计算参数a
	a_lon = avg_lon - b_lon*avg_lon_num;
	a_lat = avg_lat - b_lat*avg_lat_num;

	//console.log("b# lon:%f lat:%f a# lon:%f lat:%f", b_lon, b_lat, a_lon, a_lat);

	return [[b_lon, a_lon], [b_lat, a_lat]];
}

//计算点到直线距离
function line_distance(b, a, y, x)
{
	//公式：
	//y=bx+a==>bx-y+a=0==>Ax+By+C=0
	//d = abs[(A*_point.x+B*_point.y+C)/sqrt(A*A+B*B)]
	var d = 0.0;
	var A = b;
	var B = -1.0;
	var C = a;

	d = Math.abs((A*x+B*y+C)/Math.sqrt(A*A+B*B));

	//console.log("dis:%d", d);

	return d;
}

//统计点到直线距离分布情况
function line_distance_stat(points, begin, count)
{
	var avg_lon = 0.0;
	var avg_lon_num = 0.0;
	var avg_lat = 0.0;
	var avg_lat_num = 0.0;

	var sum_lon = 0.0;
	var sum_lat = 0.0;
	var num = begin + count;
	var a_lon = 0.0, b_lon = 0.0;
	var a_lat = 0.0, b_lat = 0.0;
	var sum_lon_dif = 0.0, sum_lat_dif = 0.0, sum_lon_same = 0.0, sum_lat_same = 0.0;

	//求和
	for (var i = begin; i < num; i++) {
		sum_lon += points[i][0];
		sum_lat += points[i][1];
	}

	avg_lon = sum_lon/count;
	avg_lat = sum_lat/count;

	avg_lat_num = avg_lon_num = (1+count)*count/2/count;

	//计算参数b
	for (var i = begin; i < num; i++) {
		sum_lon_dif += (points[i][0] - avg_lon)*(i - begin - avg_lon_num);
		sum_lon_same += (points[i][0] - avg_lon)*(points[i][0] - avg_lon);

		sum_lat_dif += (points[i][1] - avg_lat)*(i - begin - avg_lat_num);
		sum_lat_same += (points[i][1] - avg_lat)*(points[i][1] - avg_lat);
	}

	//console.log("#%d diff# lon:%f lat:%f same# lon:%f lat:%f", begin, sum_lon_dif, sum_lat_dif, sum_lon_same, sum_lat_same);

	b_lon = sum_lon_dif/sum_lon_same;
	b_lat = sum_lat_dif/sum_lat_same;

	//计算参数a
	a_lon = avg_lon - b_lon*avg_lon_num;
	a_lat = avg_lat - b_lat*avg_lat_num;

	console.log("b# lon:%f lat:%f a# lon:%f lat:%f", b_lon, b_lat, a_lon, a_lat);

	//return [[b_lon, a_lon], [b_lat, a_lat]];
	
	//统计点到直线的距离
	var dis_lon = [], dis_lat = [];
	for (var i = begin; i < num; i++) {
		var d_lon = line_distance(b_lon, a_lon, i-begin, points[i][0]);
		dis_lon.push(d_lon);

		var d_lat = line_distance(b_lat, a_lat, i-begin, points[i][1]);
		dis_lat.push(d_lat);

		console.log("(d# (%d,%f, %f), #lon:%f lat:%f", i, points[i][0], points[i][1], d_lon, d_lat);
	}

	//判定点到直线的距离的偏差
	//表达偏差可以使用
	var ss_lon = 0.0, ss_lat = 0.0;
	for (var i = begin; i < num; i++) {
		ss_lon += (points[i][0] - avg_lon)*(points[i][0] - avg_lon);
		ss_lat += (points[i][1] - avg_lat)*(points[i][1] - avg_lat);
	}
	
	console.log("ss# lon:%f lat:%f", ss_lon, ss_lat);
	
	return ;
}

function draw_markers(mode)
{
    var _lastpoint = [0,0];
    var _above = 0;
    var points = [];
    var speeds = [];
    var cnos = [];

    //提取记录点
	for (var i = 0; i < data.data.length; i++) {
        var _point = wgs2bd(data.data[i][1], data.data[i][0]);
        var _speed = data.speed[i];
        var _cno = data.heading[i];

        points.push(_point);
        speeds.push(_speed);
        cnos.push(_cno);
	}

	var t = 5;
	var tt = 49;
	var start = 1100;
	var end = 1300;//data.data.length;
	var _lastpoint;
	var _histpoint;
	var watch_flag = 0;	//判断条件，速度递减
	var d_speed_count = 0;	//速度递减次数
	var contiue_d_count = 0; //连续减速

	var d_flag = 0;	//降速
	var stop_flag = 0;	//静止标志
	var jump_flag = 0;	//跳跃标志

	//var nor_points = normalize(points);	
	//console.log("len:%d %d", _histpoint.length, points.length);

    for (var i = start; (i < end) && (mode & 0x1); ) {
        var _point = points[i];
        var _cno = cnos[i];
        var _speed = speeds[i];
        var _bPoint;
        
        _histpoint = points[i].slice();

        /*
        //alg4过滤运动点的偏离
        //a 统计50个临近点
        if (i >= start + tt)
        {
        	//line_distance_stat(points, i-tt, tt);
        }
        
        //alg3可用于抑制运动过程大的漂移,统计临近点的记录变化，以及平均速度
		if (i >= start + 5 && 1)
        {
        	_bPoint = points[i-t];
        	var v = 0;
        	var dis = 0;
        	var d = 0;
        	var d1= 0;

        	//计算速度平均值
        	for (var j = 0; j <= 5; j ++) {
        		v += speeds[i-t+j];
        	}

        	v /=6;

        	//计算前5个点的距离差平均值
        	var v_lon = 0, v_lat = 0;

        	for (var j = 1; j < 5; j ++) {
        		var p1 = new BMap.Point(points[i-t+j-1][1], points[i-t+j-1][0]);
        		var p2 = new BMap.Point(points[i-t+j][1], points[i-t+j][0]);

        		var tmp = bm.getDistance(p1,p2)
        		if (isNaN(tmp))
        			tmp = 0;
        		dis += tmp;
        		// if (i == 21)
        		// {
        		// 	console.log("dis# %f [%f,%f] [%f,%f]", dis, p1.lng, p1.lat, p2.lng, p2.lat);
        		// }
        		//dis += getDistance(points[i-t+j-1], points[i-t+j]);
        		//dis += getD(p1,p2);
        		//
        		v_lon += p2.lng - p1.lng;
        		v_lat += p2.lat - p1.lat;
        	}

        	dis /= 4.0;
        	v_lon /=4.0;
        	v_lat /=4.0;

        	//计算最后两个点的距离
        	var p1 = new BMap.Point(points[i-t+4][1], points[i-t+4][0]);
        	var p2 = new BMap.Point(points[i-t+5][1], points[i-t+5][0]);
        	d = bm.getDistance(p1,p2);

        	//p1 = new BMap.Point(points[i-t+3][1], points[i-t+3][0]);
        	//p2 = new BMap.Point(points[i-t+5][1], points[i-t+5][0]);
        	//d1 = bm.getDistance(p1,p2);

        	//d = getDistance(points[i-t+4], points[i-t+5]);
        	
        	//d1 = getD(p1,p2);

        	//console.log("%d# dis:%f d:%f d1:%f v_lon:%f v_lat:%f", i, dis, d, d1, v_lon, v_lat);

        	//如果最后两个点超过4倍平局距离，并且当前点跳跃超过30m，则认为是跳跃。
        	//如果能够拿到时间间隔，可以添加一个时间条件来判断大的跳跃。
        	if (v >= 2)
        	{
				if (dis >= 2 && d > 4.0*dis && d > 30) {
	        		jump_flag = 1;
	        	}
				else
				{
					jump_flag = 0;
				}
        	}        	

			//过滤跳跃点
			if (jump_flag == 1) {
				//if ((_histpoint[i-1][0] != points[i][0]) && (_histpoint[i-1][1] != points[i][1]))
				{
					//points[i][0] = points[i-1][0] + v_lat*1.5;
					//points[i][1] = points[i-1][1] + v_lon*1.5;
					//_point = points[i];
					_point[0] = points[i-1][0] + v_lat*1.5;
					_point[1] = points[i-1][1] + v_lon*1.5;
					
				}
				// else
				// {
				// 	points[i] = _histpoint[i-1];
				// }
				
				console.log("%d# [%f, %f] [%f, %f]", i, points[i][0], points[i][1], points[i-1][0], points[i-1][1]);
			}
        }
        */

        /*
        //alg2可用于抑制单点静止状态的漂移
		if (i >= start + 5 && 1)
        {
        	_bPoint = points[i-t];
        	var v = (speeds[i-t+0] + speeds[i-t+1] + speeds[i-t+2] + speeds[i-t+3] + speeds[i-t+4] + speeds[i-t+5])/6;
        	
        	//a 判断速度是否都很低，并且几乎为0m/s
        	//速度已经降到4m/s以下
        	//连续6个点平均速度低于3m/s，当前速度低于2m/s
        	if (v < 3 && speeds[i] < 2) {
        		var zero_count = 0;
        		for (var j = 0; j < 5; j++) {
        			if (speeds[i-5+j] == 0 )
        				zero_count ++;
        		}

        		//6个点至少5个点速度为0
        		if (zero_count > 4) {
        			stop_flag = 1;
        		}
        		//else
        		//	stop_flag = 0;
        	}

        	//b 判断是否已经运动，可以考虑使用alg1中的运动判断
        	if (v >= 1 || speeds[i] >= 2) 
        	{
        		stop_flag = 0;
        	}

        	//c 静止过程，判断过滤漂移点
        	if (stop_flag) {
				//if (_speed <= 5)
		        {
		            _point = _lastpoint;
		        }
        	}
        }
        */

        //alg1可用于抑制路口等待导致的偏移
        //使用连续减速与连续加速为先验条件，然后过滤减速到静止过程造成的点漂移
        /*
        if (i >= start + 5 && 1)
        {
        	_bPoint = points[i-t];
        	var p1 = new BMap.Point(_bPoint[1], _bPoint[0]);
        	var p2 = new BMap.Point(_point[1], _point[0]);

        	var dis = bm.getDistance(p1,p2);
        	var v = (speeds[i-t+0] + speeds[i-t+1] + speeds[i-t+2] + speeds[i-t+3] + speeds[i-t+4] + speeds[i-t+5])/6;

        	//console.log("id:%d dis:%d, v:%d, v1:%d", i, dis, v, dis/5);

        	//a 判断连续减速趋势
        	//速度已经降到5m/s以下
        	//第i个点与第i-5个点速度至少相差4m/s
        	if (speeds[i-5] - speeds[i] >= 4 && speeds[i] < 5) {
        		var d_count = 0;
        		for (var j = 0; j < 5; j++) {
        			if (speeds[i-5+j] > speeds[i-5+j+1] )
        				d_count ++;
        		}

        		//6个点至少三次降速
        		if (d_count > 3) {
        			d_flag = 1;
        		}
        	}

        	//b 判断连续加速趋势
        	//速度已经高于5m/s
        	//统计临近6个点的速度值增量变化
			if (speeds[i] > 5) {
        		var i_count = 0;
        		for (var j = 0; j < 5; j++) {
        			if (speeds[i-5+j] < speeds[i-5+j+1] )
        				i_count ++;
        		}

        		//6个点至少三次降速
        		if (i_count > 3) {
        			d_flag = 0;
        		}
        	}

        	//c 降速过程，判断过滤漂移点
        	if (d_flag) {
				//if (_speed <= 5)
		        {
		            _point = _lastpoint;
		        }
        	}
        }
        //*/
       
       	_lastpoint = _point;
        create_markers(i, _point, _cno, _speed);

        //还原points
        points[i] = _histpoint;

        i+= 1;
    }
}

function check_draw()
{
    mode = 0;
    if (document.getElementById("188").checked)
        mode += 1;
    if (document.getElementById("180").checked)
        mode += 2;
    if (document.getElementById("android").checked)
        mode += 4;

    bm.clearOverlays();
    draw_markers(mode);
}

draw_markers(7);

</script>

</body>
</html>
